using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Miwik_NodePath
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {

    #region fields

        // engine and render
        private DARE.CDare m_Dare;
        private DARE.CScene m_scene;
        private DARE.CRender3D m_render;

        // camera
        private DARE.CFirstPersonCamera m_firstCam;
        private Vector3 m_moveCam;

        // key state
        private bool m_rightButtonPressed;
        private bool m_leftButtonPressed;
        private bool m_ctrlPressed;
        private bool m_upPressed;
        private bool m_downPressed;
        private bool m_fPressed;
        private bool m_autoRun;
        private bool m_leftPressed;
        private bool m_rightPressed;

        // node
        private DARE.CNodePath m_nodePath;
        private DARE.CNode m_pointer;
        private int m_selected;
        private bool m_select;
        private float m_distance;
        private float m_pathDistance = 0;
        private DARE.CNode m_pathPointer;
        private DARE.CNode m_tangentPointer;
        private List<DARE.CNode> m_trackNode;
        private int m_speed = 2;

    #endregion

    #region ctor

        public Game1()
        {
            // create the engine
            m_Dare = new DARE.CDare(this);
        }

        protected override void Initialize()
        {
            m_moveCam = Vector3.Zero;
            m_rightButtonPressed = false;
            m_leftButtonPressed = false;
            m_autoRun = false;
            m_trackNode = new List<DARE.CNode>();
            base.Initialize();
        }

    #endregion

    #region load/unload content

        protected override void LoadContent()
        {
            // general configuration
            m_Dare.Config.General.WindowTitle = "NodePath Demo LAWL !!!!";
            m_Dare.Config.General.ShowMouseCursor = true;
            m_Dare.Config.General.ShowDebugConsole = true;

            // video configuration
            m_Dare.Config.Video.SetResolution(1024, 768);
            m_Dare.Config.Video.FullScreen = false;
            m_Dare.Config.Video.MultiSampling = true;
            m_Dare.Config.Video.UnlockFps = true;

            // start the engine
            m_Dare.RockNRoll();

            // scene creation
            CreateRender();
            CreateCamera();
            CreateScene();
        }

    #endregion

    #region scene creation

        private void CreateRender()
        {
            // simple use, only one scene and one render
            m_scene = new DARE.CScene("scene");
            m_render = new DARE.CRender3D("render", new DARE.COctree(-1000, 1050, -1000, 1050, -1050, 1000));

            // register our renderer to the scene
            m_scene.RegisterRenderer(m_render);
        }

        private void CreateCamera()
        {
            // create our first person camera
            m_firstCam = new DARE.CFirstPersonCamera("firstCam");
            m_firstCam.Translate(new Vector3(0, 25, 0));
            m_firstCam.LookAt(new Vector3(25, 0, -25));

            // register the camera
            m_render.CameraMgr.RegisterCamera(m_firstCam);
        }

        private void CreateScene()
        {
            



            // display a welcome message
            DisplayWelcomeMessage();

            // show options
            m_render.FillMode = FillMode.Solid;
            m_render.ShowModelNode = true;
            m_render.Partitioner.Show = false;
            m_render.Partitioner.ShowItems = true;

            // display a custom floor and sky in the scene
            DARE.CNode nFloor = m_render.CreateNode("nFloor");
            nFloor.Entity.AttachModel(new DARE.CFloorModel());
            nFloor.AABB = new BoundingBox(new Vector3(0, -1, -50), new Vector3(50, 1, 0));
            ((DARE.CBasicModel)nFloor.Entity.Model).FillMode = FillMode.WireFrame;
            m_render.SkyMgr.CreateSkybox("Sky", "sky/ct");

            m_pointer = m_render.CreateNode("nPointer");
            //m_pointer.Entity.CreateBasicSphere(0.4f);
            m_pointer.Entity.CreateBasicBox(0.7f, 0.7f, 0.7f);
            ((DARE.CBasicModel)m_pointer.Entity.Model).Color = Color.Green;
            m_pointer.Entity.Model.IsTransparent = true;

            m_pathPointer = m_render.CreateNode("nPathPointer", DARE.EType.DYNAMIC);
            //m_pathPointer.Entity.CreateBasicBox(1, 0.1f, 0.7f);
            DARE.CModel ship = new DARE.CModel("ship", "Models/Ship");
            ship.Effect.ColorMap = DARE.CResourceMgr.Load<Texture2D>("Models/ShipDiffuse");
            ship.Scale = Vector3.One / 1200;
            ship.Offset = Vector3.UnitY / 2;
            m_pathPointer.Entity.AttachModel(ship);

            //m_pathPointer.Smooth = true;

            m_pathPointer.CreateChild(DARE.EType.DYNAMIC).TranslateZ(-1);

            m_tangentPointer = m_render.CreateNode("nTangentPointer", DARE.EType.DYNAMIC);
            //m_tangentPointer.Entity.CreateBasicSphere(0.2f);

            DARE.CNode cam = m_pathPointer.CreateChild("nCam", DARE.EType.DYNAMIC).Translate(0, 1.8f, 4).Pitch(-0.12f);
            cam.Smooth = true;
            cam.SmoothAmount = 0.03f;

            m_select = false;
            m_selected = -1;

            // test
            NodePath();



            m_render.EffectMgr.LighteningEnabled = true;

            m_render.EffectMgr.AmbientLightColor = Color.White;
            m_render.EffectMgr.AmbientLightIntensity = 0.1f;

            m_render.EffectMgr.DirectionalLight0Direction = new Vector3(0.6f, -1, 0.8f);
            m_render.EffectMgr.DirectionalLight0DiffuseColor = Color.White;
            m_render.EffectMgr.DirectionalLight0DiffuseIntensity = 1.0f;

        }

        private void NodePath()
        {
            DemoNodePath0(2);
            //RandomNodePath(10);

            m_Dare.DebugMgr.DebugConsole.WriteLine("node path length = " + m_nodePath.Length.ToString());
        }

        private void DemoNodePath0(int number)
        {
            if (m_nodePath == null)
                m_nodePath = new DARE.CNodePath(m_render);
            m_nodePath.Clear();

            float pitch = 0.05f;

            for (int i = 0; i < number; ++i)
            {
                if (i == 0)
                    m_nodePath.AddNode(25, i * 4 + 0, 0, -MathHelper.PiOver2, pitch, 0, 0.4f);
                else
                    m_nodePath.AddNode(25, i * 4 + 0, -5, -MathHelper.PiOver2, pitch, 0, 0.4f);

                m_nodePath.AddNode(45, i * 4 + 1, -25, 0, 0, 0, 0.4f);
                m_nodePath.AddNode(25, i * 4 + 2, -45, MathHelper.PiOver2, pitch, 0, 0.4f);

                if (i == number - 1)
                    m_nodePath.AddNode(0, i * 4 + 3, -25, MathHelper.Pi, pitch, 0, 0.4f);
                else
                    m_nodePath.AddNode(5, i * 4 + 3, -25, MathHelper.Pi, pitch, 0, 0.4f);
            }
        }

        private float RandomNodePath(int number)
        {
            float minDist = 30;
            int minPosX = -50; int maxPosX = 100;
            int minPosY = 0; int maxPosY = 10;
            int minPosZ = -100; int maxPosZ = 50;
            int minRotX = 0; int maxRotX = (int)(MathHelper.Pi * 100);
            int minRotY = 0; int maxRotY = (int)(MathHelper.Pi * 100);
            int minRotZ = -(int)(((MathHelper.Pi * 100) / MathHelper.Pi) / 6); 
            int maxRotZ = (int)(((MathHelper.Pi * 100) / MathHelper.Pi) / 6);

            Vector3 pos = new Vector3();
            Vector3 lastPos = pos;
            Vector3 rot = new Vector3();

            if (m_nodePath == null)
                m_nodePath = new DARE.CNodePath(m_render);
            m_nodePath.Clear();

            for (int i = 0; i < number; ++i)
            {
                while (Vector3.Distance(lastPos, pos) < minDist)
                {
                    pos.X = m_Dare.Random.Next(minPosX, maxPosX);
                    pos.Y = m_Dare.Random.Next(minPosY, maxPosY);
                    pos.Z = m_Dare.Random.Next(minPosZ, maxPosZ);
                }
                lastPos = pos;

                rot.X = m_Dare.Random.Next(minRotX, maxRotX) / 100.0f;
                rot.Y = m_Dare.Random.Next(minRotY, maxRotY) / 100.0f;
                rot.Z = m_Dare.Random.Next(minRotZ, maxRotZ) / 100.0f;

                m_nodePath.AddNode(pos, Quaternion.CreateFromYawPitchRoll(rot.Y, rot.X, rot.Z));
            }
            return m_nodePath.Length;
        }

        private void DrawTrack()
        {
            DARE.CNode main = null;
            DARE.CNode right = null;
            DARE.CNode left = null;
            DARE.CNode join = null;
            Quaternion orientation = Quaternion.Identity;
            float space = 3;

            DeleteTrack();
            for (float i = 0; i < m_nodePath.Length; i += space)
            {
                main = m_render.CreateNode().SetPosition(m_nodePath.GetPosDistance(i, out orientation));
                //main.LookAt(main.Position + tangent);
                main.SetOrientation(orientation, DARE.CNode.ESpace.WORLD);
                main.Entity.CreateBasicBox(2.5f, 0.1f, 1);
                ((DARE.CBasicModel)main.Entity.Model).Color = Color.White;
                //main.Entity.Model.IsTransparent = true;

                right = main.CreateChild();
                right.Translate(1.5f, 0.5f, 0);
                right.Roll(-0.3f);
                right.Entity.CreateBasicBox(0.1f, 0.8f, 1);
                ((DARE.CBasicModel)right.Entity.Model).Color = Color.White;
                //right.Entity.Model.IsTransparent = true;

                left = main.CreateChild();
                left.Translate(-1.5f, 0.5f, 0);
                left.Roll(0.3f);
                left.Entity.CreateBasicBox(0.1f, 0.8f, 1);
                ((DARE.CBasicModel)left.Entity.Model).Color = Color.White;
                //left.Entity.Model.IsTransparent = true;

                join = m_render.CreateNode().SetPosition(m_nodePath.GetPosDistance(i - space / 2, out orientation));
                //join.LookAt(join.Position + tangent);
                join.SetOrientation(orientation, DARE.CNode.ESpace.WORLD);
                join.Entity.CreateBasicBox(1, 0.1f, 1.5f);
                ((DARE.CBasicModel)join.Entity.Model).Color = Color.Red;
                join.Entity.Model.IsTransparent = true;
                join.Entity.Model.Transparency = 0.4f;

                m_trackNode.Add(main);
                m_trackNode.Add(right);
                m_trackNode.Add(left);
                m_trackNode.Add(join);
            }
        }

        private void DeleteTrack()
        {
            foreach (DARE.CNode node in m_trackNode)
                m_render.RemoveNode(node);
        }

    #endregion

    #region run

        protected override void Update(GameTime gameTime)
        {
            ProcessKeyPressed();
            ProcessKeyReleased();
            ProcessMousePressed();
            ProcessMouseReleased();
            ProcessMouseMoved();
            ProcessMouseWheel();
            ProcessRaycast();
            ApplyMovement();
            base.Update(gameTime);
        }

        private void ProcessRaycast()
        {
            //foreach (DARE.CRayCast.CIntersectInfo info in m_render.RayCast.IntersectOrderFromCenterToMouse())
            //{

            //}
        }

        private int ticks = 0;

        private void ApplyMovement()
        {
            float fixedTime = m_Dare.Config.Time.FixedTimeSinceLastFrame;
            float fixedMoveSpeed = fixedTime / 200.0f;
            float fixedRotateSpeed = fixedTime / 500.0f;

            if (m_rightButtonPressed)
            {
                if (m_ctrlPressed)
                    fixedMoveSpeed *= 20;
                m_firstCam.Translate(m_moveCam * fixedMoveSpeed * 2);
            }

            if (m_select)
            {
                m_pointer.SetPosition(m_firstCam.Position, DARE.CNode.ESpace.WORLD);
                m_pointer.Translate(m_firstCam.Orientation, -Vector3.UnitZ * m_distance, DARE.CNode.ESpace.WORLD);
                if (m_leftPressed)
                    m_pointer.Roll(fixedRotateSpeed, DARE.CNode.ESpace.LOCAL);
                else if (m_rightPressed)
                    m_pointer.Roll(-fixedRotateSpeed, DARE.CNode.ESpace.LOCAL);

                // ==================
                if (++ticks >= 3)
                {
                    m_nodePath.SetNode(m_selected, m_pointer.Position, m_pointer.Orientation, m_nodePath.Weights[m_selected]);
                    ticks = 0;
                }
            }

            // ===================== CURVE ======================

            if (m_upPressed || m_autoRun)
                m_pathDistance += fixedMoveSpeed * m_speed;
            else if (m_downPressed)
                m_pathDistance -= fixedMoveSpeed * m_speed;
            if (m_pathDistance > m_nodePath.Length)
                m_pathDistance = 0;
            else if (m_pathDistance < 0)
                m_pathDistance = m_nodePath.Length;

            Quaternion orientation;
            Vector3 pos = m_nodePath.GetPosDistance(m_pathDistance, out orientation);

            //tangent.Normalize();
            
            m_pathPointer.SetPosition(pos, DARE.CNode.ESpace.WORLD);
            m_pathPointer.SetOrientation(orientation, DARE.CNode.ESpace.WORLD);
            //m_pathPointer.LookAt(m_pathPointer.Position + tangent);
            //m_tangentPointer.SetPosition(m_pathPointer.Position + tangent, DARE.CNode.ESpace.WORLD);

            //m_pathPointer.Rotate(0, 0, 1);

            if (m_fPressed)
                m_firstCam.LookAt(m_pathPointer.Position);

            // ========== DEBUG ==========
            m_Dare.DebugMgr.DebugConsole.WriteLine("ship Yaw = " + MathHelper.ToDegrees(m_pathPointer.Node.NYaw));
            m_Dare.DebugMgr.DebugConsole.WriteLine("ship Pitch = " + MathHelper.ToDegrees(m_pathPointer.Node.NPitch));
            m_Dare.DebugMgr.DebugConsole.WriteLine("ship Roll = " + MathHelper.ToDegrees(m_pathPointer.Node.NRoll));
            m_Dare.DebugMgr.DebugConsole.WriteLine("");

            m_Dare.DebugMgr.DebugConsole.WriteLine("pointer Yaw = " + MathHelper.ToDegrees(m_pointer.NYaw));
            m_Dare.DebugMgr.DebugConsole.WriteLine("pointer Pitch = " + MathHelper.ToDegrees(m_pointer.Node.NPitch));
            m_Dare.DebugMgr.DebugConsole.WriteLine("pointer Roll = " + MathHelper.ToDegrees(m_pointer.Node.NRoll));
            m_Dare.DebugMgr.DebugConsole.WriteLine("");

            Quaternion conjugateYaw = Quaternion.CreateFromYawPitchRoll(m_pointer.NYaw, 0, 0);
            conjugateYaw.Conjugate();
            Quaternion conugatePitch = Quaternion.CreateFromYawPitchRoll(0, m_pointer.NPitch, 0);
            conugatePitch.Conjugate();

            m_pointer.Orientation *= conjugateYaw;
            m_pointer.Orientation *= conugatePitch;

            //m_pathPointer.SetRoll(0, DARE.CNode.ESpace.WORLD);
            // m_firstCam.Node.SetRoll(0, DARE.CNode.ESpace.WORLD);
        }

        private Texture2D dare = null;

        protected override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            if (dare == null)
                dare = DARE.CResourceMgr.Load<Texture2D>("Logo/DARE_small");
            m_Dare.SpriteBatch.Begin();
            m_Dare.SpriteBatch.Draw(dare, new Rectangle(0, 0, (int)(dare.Width / 1.5f), (int)(dare.Height / 1.5f)), Color.White);
            m_Dare.SpriteBatch.End();
        }

    #endregion

    #region input

        private void ProcessKeyPressed()
        {
            foreach (Keys key in m_Dare.InputMgr.Keyboard.KeyPressedEvent)
                switch (key)
                {
                    // exit / usage
                    case Keys.Escape: this.Exit(); break;
                    case Keys.Tab: DisplayUsage(); break;

                    // video settings
                    case Keys.F1:
                        m_Dare.Config.Video.SetResolution(1024, 768);
                        m_Dare.Config.Video.FullScreen = false;
                        break;
                    case Keys.F2:
                        m_Dare.Config.Video.SetResolution(1680, 1050);
                        m_Dare.Config.Video.FullScreen = true;
                        break;
                    case Keys.F4: m_Dare.Config.Video.MultiSampling = !m_Dare.Config.Video.MultiSampling; break;

                    // show node model
                    case Keys.N: m_render.ShowModelNode = !m_render.ShowModelNode; break;
                    case Keys.D1: m_render.FillMode = FillMode.Solid; break;
                    case Keys.D2: m_render.FillMode = FillMode.WireFrame; break;
                    case Keys.D3: m_render.ShowCollision = !m_render.ShowCollision; break;
                    case Keys.D4: m_render.CollisionFillMode = FillMode.Solid; break;
                    case Keys.D5: m_render.CollisionFillMode = FillMode.WireFrame; break;
                    case Keys.D6: m_render.Partitioner.Show = !m_render.Partitioner.Show; break;
                    case Keys.D7: m_render.Partitioner.ShowItems = !m_render.Partitioner.ShowItems; break;
                    case Keys.D8: m_firstCam.ManualAspectRatio = !m_firstCam.ManualAspectRatio; break;
                    case Keys.D9: m_firstCam.AspectRatio += 0.1f; break;
                    case Keys.D0: m_firstCam.AspectRatio -= 0.1f; break;
                    case Keys.O: m_firstCam.FovY += 0.1f; break;
                    case Keys.P: m_firstCam.FovY -= 0.1f; break;

                    // camera
                    case Keys.W: m_moveCam.Z -= 1; break;
                    case Keys.S: m_moveCam.Z += 1; break;
                    case Keys.A: m_moveCam.X -= 1; break;
                    case Keys.D: m_moveCam.X +=1; break;
                    case Keys.LeftShift: m_moveCam.Y -= 1; break;
                    case Keys.Space: m_moveCam.Y += 1; break;
                    case Keys.LeftControl: m_ctrlPressed = !m_ctrlPressed; break;

                    case Keys.C:
                        if (m_firstCam.AttachedToNode)
                            m_firstCam.DetachFromNode();
                        else
                            m_firstCam.AttachToNode(m_render.GetNode("nCam"));
                        break;

                    // node control
                    case Keys.Q:
                        m_nodePath.AddNode();
                        break;

                    case Keys.E:
                        if (m_nodePath.Count > 0 && m_selected != -1)
                        {
                            m_select = !m_select;
                            ((DARE.CBasicModel)m_pointer.Entity.Model).Color = m_select ? Color.Red : Color.Green;
                            if (m_select)
                            {
                                m_distance = Vector3.Distance(m_firstCam.Position, m_pointer.Position);
                                m_Dare.DebugMgr.DebugConsole.WriteLine("Point " + m_selected.ToString() + " selected !");
                            }
                            else
                            {
                                m_nodePath.SetNode(m_selected, m_pointer.Position, m_pointer.Orientation, m_nodePath.Weights[m_selected]);
                                m_Dare.DebugMgr.DebugConsole.WriteLine("length = " + m_nodePath.Length.ToString());
                                m_Dare.DebugMgr.DebugConsole.WriteLine("Unselect point\n");
                            }
                        }
                        break;

                    case Keys.R:
                        if (m_select)
                        {
                            m_nodePath.RemoveNode(m_selected);
                            m_select = false;
                            m_selected = -1;
                            ((DARE.CBasicModel)m_pointer.Entity.Model).Color = Color.Green;
                            m_Dare.DebugMgr.DebugConsole.WriteLine("Point " + m_selected.ToString() + " removed !");
                        }
                        break;

                    // path
                    case Keys.Up: m_upPressed = true; break;
                    case Keys.Down: m_downPressed = true; break;
                    case Keys.F: m_fPressed = !m_fPressed; break;
                    case Keys.T: m_autoRun = !m_autoRun; break;

                    case Keys.V: DemoNodePath0(5); break;
                    case Keys.B: RandomNodePath(8); break;

                    case Keys.PageUp: m_speed += 1; break;
                    case Keys.PageDown: m_speed -= 1; break;

                    case Keys.Z: DrawTrack(); break;
                    case Keys.X: DeleteTrack(); break;

                    case Keys.G: m_nodePath.Show = !m_nodePath.Show; break;

                    case Keys.Left: m_leftPressed = true; break;
                    case Keys.Right: m_rightPressed = true; break;

                    case Keys.H: m_nodePath.UseRoll = !m_nodePath.UseRoll; break;
                    
                    default: break;
                }
        }

        private void ProcessKeyReleased()
        {
            foreach (Keys key in m_Dare.InputMgr.Keyboard.KeyReleasedEvent)
                switch (key)
                {
                    // camera
                    case Keys.W: m_moveCam.Z += 1; break;
                    case Keys.S: m_moveCam.Z -= 1; break;
                    case Keys.A: m_moveCam.X += 1; break;
                    case Keys.D: m_moveCam.X -= 1; break;
                    case Keys.LeftShift: m_moveCam.Y += 1; break;
                    case Keys.Space: m_moveCam.Y -= 1; break;

                    // path
                    case Keys.Up: m_upPressed = false; break;
                    case Keys.Down: m_downPressed = false; break;

                    case Keys.Left: m_leftPressed = false; break;
                    case Keys.Right: m_rightPressed = false; break;

                    default: break;
                }
        }

        private void ProcessMousePressed()
        {
            foreach (DARE.CMouse.EButton button in m_Dare.InputMgr.Mouse.ButtonPressedEvent)
            {
                switch (button)
                {
                    case DARE.CMouse.EButton.RIGHT: m_rightButtonPressed = true; break;
                    case DARE.CMouse.EButton.LEFT: m_leftButtonPressed = true; break;

                    default: break;
                }
                m_Dare.InputMgr.Mouse.IsCentered = m_rightButtonPressed || m_leftButtonPressed;
                m_Dare.Config.General.ShowMouseCursor = !(m_rightButtonPressed || m_leftButtonPressed);
            }
        }

        private void ProcessMouseReleased()
        {
            foreach (DARE.CMouse.EButton button in m_Dare.InputMgr.Mouse.ButtonReleasedEvent)
            {
                switch (button)
                {
                    case DARE.CMouse.EButton.RIGHT: 
                        m_rightButtonPressed = false;
                        if (m_select)
                        {
                            m_nodePath.SetNode(m_selected, m_pointer.Position, m_pointer.Orientation, m_nodePath.Weights[m_selected]);
                            m_Dare.DebugMgr.DebugConsole.WriteLine("position = " + m_pointer.Position.ToString());
                        }
                        break;
                    case DARE.CMouse.EButton.LEFT: 
                        m_leftButtonPressed = false;
                        if (m_select)
                        {
                            m_nodePath.SetNode(m_selected, m_pointer.Position, m_pointer.Orientation, m_nodePath.Weights[m_selected]);
                            m_Dare.DebugMgr.DebugConsole.WriteLine("orientation = " + m_pointer.Orientation.ToString());
                        }
                        break;

                    default: break;
                }
                m_Dare.InputMgr.Mouse.IsCentered = m_rightButtonPressed || m_leftButtonPressed;
                m_Dare.Config.General.ShowMouseCursor = !(m_rightButtonPressed || m_leftButtonPressed);
            }
        }

        private void ProcessMouseMoved()
        {
            Vector2 mouseMoved = m_Dare.InputMgr.Mouse.MoveEvent.Movement;

            // first cam orientation
            if (m_Dare.InputMgr.Mouse.HasMoved && m_rightButtonPressed)
                m_firstCam.Rotate(new Vector3(-mouseMoved.Y / 400.0f, -mouseMoved.X / 400.0f, 0.0f));
            if (m_Dare.InputMgr.Mouse.HasMoved && m_leftButtonPressed && m_select)
            {
                m_pointer.Rotate(mouseMoved.X / 200.0f, mouseMoved.Y / 200.0f, 0, DARE.CNode.ESpace.LOCAL);
            }
        }

        private void ProcessMouseWheel()
        {
            foreach (DARE.CMouseWheelEvent wheel in m_Dare.InputMgr.Mouse.WheelEvent)
            {
                bool wheelUp = wheel.WheelValue > 0 ? true : false;

                if (m_select)
                {
                    float mul = wheelUp ? 1.1f : 0.9f;

                    m_nodePath.SetNode(m_selected, m_pointer.Position, m_pointer.Orientation, m_nodePath.Weights[m_selected] * mul);
                    m_Dare.DebugMgr.DebugConsole.WriteLine("weight = " + m_nodePath.Weights[m_selected].ToString());
                    break;
                }
                if (m_nodePath.Count == 0)
                {
                    m_selected = -1;
                    m_pointer.SetPosition(Vector3.Zero, DARE.CNode.ESpace.WORLD);
                    break;
                }
                if (wheelUp)
                    m_selected = m_selected >= m_nodePath.Count - 1 ? 0 : m_selected + 1;
                else
                    m_selected = m_selected <= 0 ? m_nodePath.Count - 1 : m_selected - 1;
                m_pointer.SetPosition(m_nodePath.Nodes[m_selected].Position, DARE.CNode.ESpace.WORLD);
                m_pointer.SetOrientation(m_nodePath.Nodes[m_selected].Orientation, DARE.CNode.ESpace.WORLD);
            }
        }

    #endregion

    #region display methods

        private void DisplayWelcomeMessage()
        {
            m_Dare.DebugMgr.DebugConsole.WriteLine(
                "===========================================================================\n" + 
                "Welcome to the NodePath test area !\n" +
                "      TAB - display usage.\n" + 
                "===========================================================================\n");
        }

        private void DisplayUsage()
        {
            m_Dare.DebugMgr.DebugConsole.WriteLine(
                "===========================================================================\n" + 
                "Usage:\n" + 
                "Wheel - node selection cursor\n" + 
                "C - attach camera behind the ship\n" +
                "Q - add a node to the path\n" + 
                "E - select a node's path\n" + 
                "R - remove a node's path\n" +       
                "F - camera look at the ship\n" + 
                "Up / Down - move the ship forward / backward\n" + 
                "T - autorun\n" +
                "V - sample 1\n" + 
                "B - sample 2\n" + 
                "H - use roll\n" + 
                "===========================================================================\n");
        }

    #endregion

    }
}
